#include "klinewidget.h"

//KLineWidget::KLineWidget(QWidget *parent) : QWidget(parent)
//{

//}

KLineWidget::KLineWidget(QWidget *parent) : QWidget(parent) {
    setMouseTracking(true);
    setFocusPolicy(Qt::StrongFocus);
    setMinimumSize(1800, 900);

    // 生成示例数据
    klineData = generateKLineData(200);

    // 默认显示最后100个K线
    visibleCount = 100;
    startIndex = klineData.size() - visibleCount;
    calculateChartArea();
    // 计算价格范围
    calculatePriceRange();

    // 技术指标
    calculateMA(5);
    calculateMA(10);
    calculateMA(20);
    calculateVolumeMA(5);
}

void KLineWidget::setVisibleCount(int count) {
    visibleCount = std::max(10, std::min(count, klineData.size()));
    startIndex = klineData.size() - visibleCount;
    calculatePriceRange();
    update();
}

void KLineWidget::paintEvent(QPaintEvent *event) {
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 绘制背景
    drawBackground(painter);

    // 绘制坐标轴和网格
    drawGrid(painter);

    // 绘制K线
    drawKlines(painter);

    // 绘制技术指标
    if (showMA5) drawMA(painter, ma5, Qt::blue);
    if (showMA10) drawMA(painter, ma10, Qt::red);
    if (showMA20) drawMA(painter, ma20, Qt::green);

    // 绘制成交量
    if (showVolume) drawVolume(painter);

    // 绘制十字光标
    if (crosshairVisible) drawCrosshair(painter);

    // 绘制标题
    drawTitle(painter);
}

void KLineWidget::resizeEvent(QResizeEvent *event) {
    Q_UNUSED(event);
    calculatePriceRange();
}

void KLineWidget::mouseMoveEvent(QMouseEvent *event) {
    crosshairPos = event->pos();
    crosshairVisible = true;
    update();
}

void KLineWidget::leaveEvent(QEvent *event) {
    Q_UNUSED(event);
    crosshairVisible = false;
    update();
}

void KLineWidget::wheelEvent(QWheelEvent *event) {
    int delta = event->angleDelta().y() / 120; // 获取滚轮变化值
    setVisibleCount(visibleCount - delta * 5);
    emit visibleCountChanged(visibleCount);
}

void KLineWidget::keyPressEvent(QKeyEvent *event) {
    switch (event->key()) {
    case Qt::Key_Left:
        startIndex = std::max(0, startIndex - 5);
        update();
        break;
    case Qt::Key_Right:
        startIndex = std::min(klineData.size() - visibleCount, startIndex + 5);
        update();
        break;
    case Qt::Key_Plus:
        setVisibleCount(visibleCount + 5);
        break;
    case Qt::Key_Minus:
        setVisibleCount(visibleCount - 5);
        break;
    }
}

void KLineWidget::calculatePriceRange() {
    if (klineData.empty()) return;

    minPrice = klineData[startIndex].low;
    maxPrice = klineData[startIndex].high;
    maxVolume = klineData[startIndex].volume;

    for (int i = startIndex; i < startIndex + visibleCount; ++i) {
        if (i >= klineData.size()) break;

        minPrice = std::min(minPrice, klineData[i].low);
        maxPrice = std::max(maxPrice, klineData[i].high);
        maxVolume = std::max(maxVolume, klineData[i].volume);
    }

    // 添加一些边界空间
    double priceRange = maxPrice - minPrice;
    minPrice -= priceRange * 0.05;
    maxPrice += priceRange * 0.05;
    maxVolume *= 1.1;
}

void KLineWidget::calculateMA(int days) {
    QVector<double> *target = nullptr;
    if (days == 5) {
        ma5.clear();
        target = &ma5;
    } else if (days == 10) {
        ma10.clear();
        target = &ma10;
    } else if (days == 20) {
        ma20.clear();
        target = &ma20;
    } else {
        return;
    }

    for (int i = 0; i < klineData.size(); ++i) {
        if (i < days - 1) {
            target->append(0); // 不足周期用0填充
            continue;
        }

        double sum = 0;
        for (int j = 0; j < days; ++j) {
            sum += klineData[i - j].close;
        }
        target->append(sum / days);
    }
}

void KLineWidget::calculateVolumeMA(int days) {
    volumeMA5.clear();

    for (int i = 0; i < klineData.size(); ++i) {
        if (i < days - 1) {
            volumeMA5.append(0); // 不足周期用0填充
            continue;
        }

        double sum = 0;
        for (int j = 0; j < days; ++j) {
            sum += klineData[i - j].volume;
        }
        volumeMA5.append(sum / days);
    }
}

void KLineWidget::drawBackground(QPainter &painter) {
    // 渐变背景
    QLinearGradient gradient(0, 0, 0, height());
    gradient.setColorAt(0, QColor(25, 35, 45));
    gradient.setColorAt(1, QColor(15, 20, 30));

    painter.fillRect(rect(), gradient);

    // 绘制边框
    painter.setPen(QPen(QColor(60, 70, 80), 1));
    painter.drawRect(rect().adjusted(0, 0, -1, -1));
}

void KLineWidget::drawGrid(QPainter &painter) {
    painter.setPen(QPen(QColor(50, 60, 70), 1, Qt::DotLine));

    // 水平网格线 (价格)
    int gridLines = 5;
    for (int i = 0; i <= gridLines; ++i) {
        double price = minPrice + (maxPrice - minPrice) * i / gridLines;
        int y = priceToY(price);

        // 只在主区域绘制
        if (y < chartTop || y > chartBottom) continue;

        painter.drawLine(chartLeft, y, chartRight, y);

        // 绘制价格标签
        painter.setPen(QColor(180, 180, 180));
        painter.drawText(QRect(5, y - 10, chartLeft - 10, 20),
                         Qt::AlignRight | Qt::AlignVCenter,
                         QString::number(price, 'f', 2));
        painter.setPen(QPen(QColor(50, 60, 70), 1, Qt::DotLine));
    }

    // 垂直网格线 (时间)
    int step = std::max(1, visibleCount / 10);
    for (int i = startIndex; i < startIndex + visibleCount; i += step) {
        if (i >= klineData.size()) break;

        int x = indexToX(i);
        painter.drawLine(x, chartTop, x, chartBottom);

        // 绘制时间标签
        painter.setPen(QColor(180, 180, 180));
        QString dateStr = klineData[i].date.toString("MM-dd");
        painter.drawText(QRect(x - 30, chartBottom + 5, 60, 20),
                         Qt::AlignCenter, dateStr);
        painter.setPen(QPen(QColor(50, 60, 70), 1, Qt::DotLine));
    }
}

void KLineWidget::drawKlines(QPainter &painter) {
    // 计算K线宽度和间距
    double candleWidth = (chartRight - chartLeft) / visibleCount * 0.7;
    double spacing = (chartRight - chartLeft) / visibleCount * 0.3;

    for (int i = startIndex; i < startIndex + visibleCount; ++i) {
        if (i >= klineData.size()) break;

        const KLineData &k = klineData[i];
        int x = indexToX(i);

        // 计算坐标
        int yOpen = priceToY(k.open);
        int yClose = priceToY(k.close);
        int yHigh = priceToY(k.high);
        int yLow = priceToY(k.low);

        // 确定颜色
        QColor color = (k.close >= k.open) ? QColor(0, 200, 0) : QColor(200, 0, 0);
        painter.setPen(QPen(color, 1));

        // 绘制影线
        painter.drawLine(x, yHigh, x, yLow);

        // 绘制实体
        int candleTop = std::min(yOpen, yClose);
        int candleHeight = std::abs(yOpen - yClose);
        if (candleHeight == 0) candleHeight = 1; // 确保有高度

        // 如果涨跌实体太窄，绘制一个最小高度的实体
        if (candleHeight < 2) {
            candleTop -= 1;
            candleHeight = 2;
        }

        painter.fillRect(QRectF(x - candleWidth/2, candleTop, candleWidth, candleHeight), color);
    }
}

void KLineWidget::drawVolume(QPainter &painter) {
    // 计算成交量区域
    int volumeTop = chartBottom + 50;
    int volumeHeight = 100;

    // 绘制成交量标题
    painter.setPen(QColor(150, 150, 150));
    painter.drawText(QRect(chartLeft, volumeTop - 20, 100, 20), "exchange volume");

    // 计算柱状图宽度
    double barWidth = (chartRight - chartLeft) / visibleCount * 0.7;
    //            double spacing = (chartRight - chartLeft) / visibleCount * 0.3;

    for (int i = startIndex; i < startIndex + visibleCount; ++i) {
        if (i >= klineData.size()) break;

        const KLineData &k = klineData[i];
        int x = indexToX(i);

        // 计算柱状图高度
        int barHeight = static_cast<int>((k.volume / maxVolume) * volumeHeight);
        if (barHeight < 1) barHeight = 1;

        // 确定颜色
        QColor color = (k.close >= k.open) ? QColor(0, 200, 0, 150) : QColor(200, 0, 0, 150);

        // 绘制成交量柱状图
        painter.fillRect(QRectF(x - barWidth/2, volumeTop + volumeHeight - barHeight,
                                barWidth, barHeight), color);

        // 绘制成交量均线
        if (showVolumeMA5 && i >= 4 && volumeMA5[i] > 0) {
            int maHeight = static_cast<int>((volumeMA5[i] / maxVolume) * volumeHeight);
            int y = volumeTop + volumeHeight - maHeight;

            painter.setPen(QPen(Qt::yellow, 1.5));
            painter.drawPoint(x, y);
        }
    }
}

void KLineWidget::drawMA(QPainter &painter, const QVector<double> &ma, QColor color) {
    painter.setPen(QPen(color, 1.5));

    QPoint prevPoint;
    bool first = true;

    for (int i = startIndex; i < startIndex + visibleCount; ++i) {
        if (i >= ma.size() || ma[i] <= 0) continue;

        int x = indexToX(i);
        int y = priceToY(ma[i]);

        if (y < chartTop || y > chartBottom) continue;

        if (first) {
            first = false;
        } else {
            painter.drawLine(prevPoint, QPoint(x, y));
        }

        prevPoint = QPoint(x, y);
    }
}

void KLineWidget::drawCrosshair(QPainter &painter) {
    int x = crosshairPos.x();
    int y = crosshairPos.y();

    // 仅当在图表区域内显示十字线
    if (x < chartLeft || x > chartRight || y < chartTop || y > chartBottom)
        return;

    painter.setPen(QPen(QColor(200, 200, 200, 150), 1, Qt::DashLine));

    // 水平线
    painter.drawLine(chartLeft, y, chartRight, y);

    // 垂直线
    painter.drawLine(x, chartTop, x, chartBottom);

    // 显示价格信息
    double price = yToPrice(y);
    int index = xToIndex(x);

    painter.setPen(Qt::white);
    painter.drawText(QRect(chartLeft, chartTop - 30, chartRight - chartLeft, 20),
                     Qt::AlignCenter,
                     QString("价格: %1").arg(price, 0, 'f', 2));

    if (index >= startIndex && index < startIndex + visibleCount && index < klineData.size()) {
        const KLineData &k = klineData[index];
        QString info = QString("日期: %1  开: %2  高: %3  低: %4  收: %5  量: %6")
                .arg(k.date.toString("yyyy-MM-dd"))
                .arg(k.open, 0, 'f', 2)
                .arg(k.high, 0, 'f', 2)
                .arg(k.low, 0, 'f', 2)
                .arg(k.close, 0, 'f', 2)
                .arg(static_cast<int>(k.volume));

        painter.drawText(QRect(chartLeft, chartBottom + 30, chartRight - chartLeft, 20),
                         Qt::AlignCenter, info);
    }
}

void KLineWidget::drawTitle(QPainter &painter) {
    painter.setPen(Qt::white);
    QFont titleFont = font();
    titleFont.setBold(true);
    titleFont.setPointSize(12);
    painter.setFont(titleFont);

    painter.drawText(QRect(0, 10, width(), 30),
                     Qt::AlignCenter, "Qt K线图 - 专业金融图表");

    // 图例
    painter.setFont(font());
    painter.setPen(Qt::blue);
    painter.drawText(QRect(20, 15, 100, 20), "MA5");
    painter.setPen(Qt::red);
    painter.drawText(QRect(120, 15, 100, 20), "MA10");
    painter.setPen(Qt::green);
    painter.drawText(QRect(220, 15, 100, 20), "MA20");
}

int KLineWidget::priceToY(double price) {
    return chartBottom - static_cast<int>((price - minPrice) / (maxPrice - minPrice) * (chartBottom - chartTop));
}

double KLineWidget::yToPrice(int y) {
    return minPrice + (maxPrice - minPrice) * (chartBottom - y) / (chartBottom - chartTop);
}

int KLineWidget::indexToX(int index) {
    double position = (index - startIndex + 0.5);
    return chartLeft + static_cast<int>((position / visibleCount) * (chartRight - chartLeft));
}

int KLineWidget::xToIndex(int x) {
    double position = static_cast<double>(x - chartLeft) / (chartRight - chartLeft);
    return startIndex + static_cast<int>(position * visibleCount);
}

void KLineWidget::calculateChartArea() {
    margin = 10;
    chartTop = margin + 40;  // 顶部标题区域
    chartBottom = height() - margin - 130; // 底部成交量区域
    chartLeft = margin + 60; // 左侧价格标签区域
    chartRight = width() - margin - 10;
}
